package com.dhcc.core.api.aop;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.dhcc.core.api.config.properties.JwtProperties;
import com.dhcc.core.api.constant.ApiConst;
import com.dhcc.core.api.service.ITokenService;
import com.dhcc.core.api.shiro.ApiAuthenticationToken;
import com.dhcc.core.api.shiro.ApiSecurityManagerFactory;
import com.dhcc.core.framework.exception.BizException;
import com.dhcc.core.modules.system.entity.User;
import com.dhcc.core.modules.system.service.IUserService;

/**
 * AOP 用户登录检查--用户于api接口
 * 
 * @ClassName: ApiAuthAop
 * @Description: TODO
 * @author: cyf
 * @date: 2018年1月2日 上午10:03:14
 */
@Aspect
@Component
public class ApiAuthAop {

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private IUserService userService;

    @Autowired
    private ITokenService tokenService;

    @Autowired
    private ApiSecurityManagerFactory apiSecurityManagerFactory;

    @Pointcut(value = "@annotation(com.dhcc.core.api.annotion.ApiAuth)")
    private void cutPermission() {

    }

    @Around("cutPermission()")
    public Object doPermission(ProceedingJoinPoint point) throws Throwable {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        // 从header中获取token
        String auth = request.getHeader(jwtProperties.getHeader());

        // token为空
        if (StringUtils.isBlank(auth)) {
            throw new BizException("token不能为空");
        }

        int tokenTypeLength = jwtProperties.getTokenType().length() + 1;
        if ((auth.length() > tokenTypeLength) && auth.startsWith(jwtProperties.getTokenType() + " ")) {
            auth = auth.substring(tokenTypeLength);
            // 验证token
            tokenService.verifyToken(auth, false);
            Long userId = tokenService.getUserId(auth);
            Long deptId = tokenService.getDeptId(auth);
            User user = userService.selectById(userId);
            // 模拟shiro登录
            ApiAuthenticationToken token = new ApiAuthenticationToken(user, auth);
            Subject subject = (new Subject.Builder(apiSecurityManagerFactory.getApiSecurityManager())).buildSubject();
            subject.login(token);
            // 因为无状态，所以把信息存在request里
            request.setAttribute(ApiConst.LOGIN_USER_KEY, userId);
            request.setAttribute(ApiConst.LOGIN_USER_DEPT_KEY, deptId);
            request.setAttribute(ApiConst.LOGIN_SUBJECT, subject);
            return point.proceed();
        }
        throw new BizException("token验证失败");
    }

}
